package me.chan.chatting.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;
import me.chan.chatting.server.handler.ChatInboundHandler;
import me.chan.chatting.server.handler.GroupChatInboundHandler;
import me.chan.chatting.server.handler.GroupCreateInboundHandler;
import me.chan.chatting.server.handler.GroupJoinInboundHandler;
import me.chan.chatting.server.handler.GroupQuitInboundHandler;
import me.chan.chatting.server.handler.LoginInboundHandler;
import me.chan.chatting.server.handler.MyChannelDuplexHandler;
import me.chan.chatting.server.handler.QuitHandler;
import me.chan.chatting.server.codec.ProtocolFrameDecoder;
import me.chan.chatting.server.codec.SharableMessageCodec;

@Slf4j
public class ChattingRoomServer {


    private static final LoggingHandler LOG_HANDLER = new LoggingHandler(LogLevel.DEBUG);

    private static final SharableMessageCodec MSG_CODER = new SharableMessageCodec();

    public static void main(String[] args) {

        NioEventLoopGroup boss = new NioEventLoopGroup();
        NioEventLoopGroup worker = new NioEventLoopGroup();
        LoggingHandler LOGGING_HANDLER = new LoggingHandler(LogLevel.DEBUG);
        SharableMessageCodec MESSAGE_CODEC = new SharableMessageCodec();

        // business handlers
        LoginInboundHandler loginHandler = new LoginInboundHandler();
        ChatInboundHandler chatHandler = new ChatInboundHandler();
        GroupChatInboundHandler groupChatHandler = new GroupChatInboundHandler();
        GroupCreateInboundHandler groupCreateHandler = new GroupCreateInboundHandler();
        GroupJoinInboundHandler groupJoinHandler = new GroupJoinInboundHandler();
        GroupQuitInboundHandler groupQuitHandler = new GroupQuitInboundHandler();
        QuitHandler quitHandler = new QuitHandler();


        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.channel(NioServerSocketChannel.class);
            serverBootstrap.group(boss, worker);
            serverBootstrap.childHandler(new ChannelInitializer<NioSocketChannel>() {
                 @Override
                 protected void initChannel(NioSocketChannel ch) throws Exception {
                     ch.pipeline()
                             .addLast(new IdleStateHandler(60, 0, 0))
                             .addLast(new MyChannelDuplexHandler())
                             .addLast(new ProtocolFrameDecoder())
                             .addLast(LOGGING_HANDLER)
                             .addLast(MESSAGE_CODEC)
                             .addLast(loginHandler)
                             .addLast(chatHandler)
                             .addLast(groupChatHandler)
                             .addLast(groupCreateHandler)
                             .addLast(groupJoinHandler)
                             .addLast(groupQuitHandler)
                             .addLast(quitHandler);
                 }
             });
            Channel channel = serverBootstrap.bind(8080).sync().channel();
            channel.closeFuture().sync();
        } catch (InterruptedException e) {
            log.error("server error", e);
        } finally {
            boss.shutdownGracefully();
            worker.shutdownGracefully();
        }
    }
}
